package models

import (
	"errors"
	"github.com/robfig/revel"
	"kaibb/app/utils"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"time"
)

var (
	watchCollection   = "Location"
	cfgCollection     = "Config"
	locAttrCollection = "LocationAttr"
	DbName            = "Watch"
)

type Loc struct {
	Id                             bson.ObjectId `bson:"_id"`
	PhoneNumber, DeviceId, AddrStr string
	X, Y                           float64
	LocTime                        time.Time
}
type LocConfig struct {
	Id       bson.ObjectId `bson:"_id"`
	ScanTime int           `json:"scanTime"`
	SeverNo  string        `json:"severNo"`
}

type LocAttribute struct {
	Id             bson.ObjectId `bson:"_id"`
	Name, DeviceId string
}

//保存定位信息
func SaveLoc(phoneNumber, deviceId, addrStr string, x, y float64) error {
	revel.INFO.Printf("phoneNumber： %s deviceId: %s upload loc: %s, %s address:%s", phoneNumber, deviceId, x, y, addrStr)
	session, err := mgo.Dial(utils.DbUrl)
	watch := Loc{Id: bson.NewObjectId(), PhoneNumber: phoneNumber, DeviceId: deviceId, AddrStr: addrStr, X: x, Y: y, LocTime: time.Now()}
	locAttr := LocAttribute{Id: bson.NewObjectId(), Name: deviceId, DeviceId: deviceId}
	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	c := session.DB(DbName).C(watchCollection)
	locAttrColl := session.DB(DbName).C(locAttrCollection)
	c.Insert(&watch)
	if GetLocAttrbyDevice(deviceId) == nil {
		locAttrColl.Insert(&locAttr)
	}
	return nil
}

// 更新名称
func UpdateLocAttribute(deviceId, name string) error {
	revel.INFO.Printf("更新名称deviceId:%s,name:%s", deviceId, name)
	if GetLocAttrbyName(name) != nil {
		return errors.New(utils.NAME_EXISTS)
	}
	session, err := mgo.Dial(utils.DbUrl)
	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	c := session.DB(DbName).C(locAttrCollection)
	c.Update(bson.M{"deviceid": deviceId}, bson.M{"$set": bson.M{"name": name}})
	return nil
}

// 获取名字
func GetLocAttrs() (locAttrs []*LocAttribute) {
	revel.INFO.Printf("获取所有名称")
	session, err := mgo.Dial(utils.DbUrl)

	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	c := session.DB(DbName).C(locAttrCollection)
	c.Find(nil).All(&locAttrs)
	return
}

// 根据名字获取
func GetLocAttrbyName(name string) (locAttr *LocAttribute) {
	revel.INFO.Printf("获取名称:", name)
	session, err := mgo.Dial(utils.DbUrl)
	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	c := session.DB(DbName).C(locAttrCollection)
	c.Find(bson.M{"name": name}).One(&locAttr)
	return
}

// 根据deviceId获取
func GetLocAttrbyDevice(deviceId string) (locAttr *LocAttribute) {
	revel.INFO.Printf("获取deviceId:", deviceId)
	session, err := mgo.Dial(utils.DbUrl)
	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	c := session.DB(DbName).C(locAttrCollection)
	c.Find(bson.M{"deviceid": deviceId}).One(&locAttr)
	return
}

//更新配置
func SaveCfg(scanTime int, severNo string) error {
	revel.INFO.Printf("scanTime:%s,severNo:%s", scanTime, severNo)
	session, err := mgo.Dial(utils.DbUrl)
	var cfg = LocConfig{}
	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	c := session.DB(DbName).C(cfgCollection)
	c.Find(nil).One(&cfg)
	if cfg.Id == "" {
		cfg = LocConfig{Id: bson.NewObjectId(), ScanTime: scanTime, SeverNo: severNo}
		c.Insert(&cfg)
	} else {
		c.Update(bson.M{"_id": cfg.Id}, bson.M{"$set": bson.M{"scantime": scanTime, "severno": severNo}})
	}
	return nil
}

//获取配置
func GetCfg() (cfg *LocConfig) {
	revel.INFO.Printf("GetConfig")
	session, err := mgo.Dial(utils.DbUrl)

	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	c := session.DB(DbName).C(cfgCollection)
	c.Find(nil).One(&cfg)
	if cfg == nil {
		cfg = &LocConfig{ScanTime: 10 * 60 * 1000, SeverNo: "+8618675866658"}
	}
	return
}

func GetDeviceIds() (deviceId []string) {

	session, err := mgo.Dial(utils.DbUrl)

	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	c := session.DB(DbName).C(watchCollection)
	//select 只查询name, distinct 去重复
	c.Find(nil).Select(bson.M{"deviceid": 1}).Distinct("deviceid", &deviceId)
	revel.INFO.Println("获取所有deviceId:", deviceId)

	return
}

func GetLocations(deviceId string, start, end time.Time) (locations []*Loc) {
	revel.INFO.Println("所有Loc: %s", deviceId)

	session, err := mgo.Dial(utils.DbUrl)

	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	c := session.DB(DbName).C(watchCollection)
	//select 只查询name, distinct 去重复
	c.Find(bson.M{"deviceid": deviceId, "loctime": bson.M{"$gte": start, "$lte": end}}).Sort("-loctime").All(&locations)
	return
}
